#include "app_epd.h"
#include "app_priv.h"

epd_handle_t *g_epd = NULL;

static const char *TAG = "app_epd";
static SemaphoreHandle_t s_semph_image_updated = NULL;

esp_err_t app_epd_init(void)
{
    // 初始化 EPD 端口
    static epd_port_t s_epd_port = {
        .busy_io_num = EPD_PIN_BUSY,
        .reset_io_num = EPD_PIN_RESET,
        .dc_io_num = EPD_PIN_DC,
        .cs_io_num = EPD_PIN_CS,
        .sck_io_num = EPD_PIN_SCK,
        .sda_io_num = EPD_PIN_SDA,
        .host_id = EPD_SPI_HOST,
        .queue_size = EPD_SPI_QUEUE_SIZE,
        .clock_speed_hz = EPD_SPI_CLOCK_HZ,
        .max_transfer_sz = EPD_SPI_MAX_TRANSFER_SZ};
    esp_err_t ret = epd_port_init(&s_epd_port);
    if (ret != ESP_OK)
    {
        return ret;
    }
    // 初始化 EPD 句柄
    static uint8_t s_dis_buf[EPD_DIS_BUF_SIZE] = {0};
    static epd_handle_t s_handle = {
        .width = EPD_WIDTH,
        .height = EPD_HEIGHT,
        .dis_buf_size = EPD_DIS_BUF_SIZE,
        .dis_buf = s_dis_buf,
        .port = &s_epd_port,
    };
    g_epd = &s_handle;
    // 初始化 EPD 显示
    ret = epd_init(g_epd);
    if (ret != ESP_OK)
    {
        return ret;
    }
    // 创建图像更新信号量
    s_semph_image_updated = xSemaphoreCreateBinary();
    if (s_semph_image_updated == NULL)
    {
        ESP_LOGE(TAG, "Failed to create image updated semaphore");
        return ESP_FAIL;
    }
    return ret;
}

static esp_err_t update_image(const char *e6_filename)
{
    MEASURE_FUNC(epd_wake(g_epd));                     // Wake up from sleep.
    MEASURE_FUNC(epd_dis_e6_file(g_epd, e6_filename)); // Display E6 file image.
    MEASURE_FUNC(epd_sleep(g_epd));                    // Enter the sleep mode and please do not delete it, otherwise it will reduce the lifespan of the screen.

    return ESP_OK;
}

void app_epd_run(void *arg)
{
    const char *e6_filename = (const char *)arg;
    MEASURE_FUNC(app_epd_init()); // Full screen refresh initialization.
    // MEASURE_FUNC(EPD_Display_White());
    MEASURE_FUNC(epd_fill_screen(g_epd, EPD_WHITE)); // Fill screen with white color.
    DELAY_MS(1000);
    // // MEASURE_FUNC(EPD_Display_Black());
    // MEASURE_FUNC(epd_fill_screen(g_epd, EPD_BLACK)); // Fill screen with black color.
    // DELAY_MS(5000); // Delay for 5s.
    // // MEASURE_FUNC(EPD_Display_Yellow());
    // MEASURE_FUNC(epd_fill_screen(g_epd, EPD_YELLOW)); // Fill screen with yellow color.
    // DELAY_MS(5000); // Delay for 5s.
    // // MEASURE_FUNC(EPD_Display_Blue());
    // MEASURE_FUNC(epd_fill_screen(g_epd, EPD_BLUE)); // Fill screen with blue color.
    // DELAY_MS(5000); // Delay for 5s.
    // MEASURE_FUNC(epd_fill_screen(g_epd, EPD_GREEN)); // Fill screen with green color.
    // DELAY_MS(5000); // Delay for 5s.
    // MEASURE_FUNC(epd_fill_screen(g_epd, EPD_RED)); // Fill screen with red color.
    // DELAY_MS(5000); // Delay for 5s.
    // MEASURE_FUNC(epd_init_fast(g_epd));         // Full screen refresh initialization.
    // MEASURE_FUNC(epd_wake(g_epd));              // Wake up from sleep.
    // MEASURE_FUNC(epd_dis_pic(g_epd, gImage_1)); // Display image.
    // MEASURE_FUNC(epd_sleep(g_epd));             // Enter the sleep mode and please do not delete it, otherwise it will reduce the lifespan of the screen.
    // DELAY_MS(5000);                             // Delay for 5s.
    // MEASURE_FUNC(epd_init_fast(g_epd));                  // Fast initialization.
    // MEASURE_FUNC(epd_wake(g_epd)); // Wake up from sleep.
    // MEASURE_FUNC(epd_clear(g_epd)); // Clear the display.
    // DELAY_MS(500);
    // MEASURE_FUNC(epd_dis_pic(g_epd, image_xiaoye_data)); // Display image.
    // MEASURE_FUNC(epd_sleep(g_epd));                      // Enter the sleep mode and please do not delete it, otherwise it will reduce the lifespan of the screen.
    // ESP_LOGI(TAG, "epd demo completed");

    update_image(e6_filename);

    while (1)
    {
        // 等待图像更新通知
        if (xSemaphoreTake(s_semph_image_updated, portMAX_DELAY) == pdTRUE)
        {
            ESP_LOGI(TAG, "Image update notified, displaying image: %s", e6_filename);
            // 更新显示图像
            update_image(e6_filename);
            ESP_LOGI(TAG, "Image displayed");
        }
    }

    vTaskDelete(NULL);
}

esp_err_t app_epd_notify_image_updated(void)
{
    if (s_semph_image_updated != NULL)
    {
        xSemaphoreGive(s_semph_image_updated);
        return ESP_OK;
    }
    return ESP_FAIL;
}